import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
import dalex as dx
import pickle
import warnings
import matplotlib.pyplot as plt
warnings.filterwarnings('ignore')
df = pd.read_csv('heart_data.csv')
y = df.target.values
x = df.drop(['target'], axis = 1)
x_train, x_test, y_train, y_test = train_test_split(x,y, test_size = 0.2,random_state=0, stratify=y)
knn = pickle.load(open("Modele/knn", 'rb'))
rf = pickle.load(open("Modele/random_forest", 'rb'))
ss = StandardScaler()
ss.fit(x_train, y_train)
p_knn = Pipeline(
[
('standardscaler', ss),
('KNN', knn)
]
)
p_rf = Pipeline(
[
('Random Forest', rf)
]
)
p_svc = Pipeline(
[
('standardscaler', ss),
('SVC', SVC( C = 0.5, random_state=1, probability=True))
]
)
p_svc.fit(x_train, y_train)
pipelines = [p_knn, p_rf, p_svc]
e_knn = dx.Explainer(p_knn, x_train, y_train, label = "KNN", verbose=0)
e_svc = dx.Explainer(p_svc, x_train, y_train, label = "SVC", verbose=0)
e_rf = dx.Explainer(p_rf, x_train, y_train, label = "Random Forest", verbose=0)
mp_knn = e_knn.model_profile()
mp_svc = e_svc.model_profile()
mp_rf = e_rf.model_profile()
Calculating ceteris paribus: 100%|█████████████████████████████████████████████████████| 20/20 [00:16<00:00, 1.24it/s] Calculating ceteris paribus: 100%|█████████████████████████████████████████████████████| 20/20 [00:19<00:00, 1.01it/s] Calculating ceteris paribus: 100%|█████████████████████████████████████████████████████| 20/20 [00:37<00:00, 1.88s/it]
var = ['age', 'sex', 'chol', 'thalach', 'exang', 'oldpeak', 'ca','cp_ta', 'thal_n', 'thal_rd']
Z podwodu wielkości pliku musiałem wrzucić wykresy jako zdjęci PDP_geom.png
Na poniższych wykresach zajmę się klikoma zmiennymi które mają największą zmienność.
#mp_rf.plot(variables=var, geom="profiles")
mp_rf.plot([mp_knn, mp_svc], variables=var)
ale_rf = e_rf.model_profile(type = 'accumulated')
pdp_rf = e_rf.model_profile(type = 'partial')
Calculating ceteris paribus: 100%|█████████████████████████████████████████████████████| 20/20 [00:45<00:00, 2.30s/it] Calculating accumulated dependency: 100%|██████████████████████████████████████████████| 20/20 [00:02<00:00, 9.64it/s] Calculating ceteris paribus: 100%|█████████████████████████████████████████████████████| 20/20 [00:44<00:00, 2.24s/it]
Po porówaniu wykresów obu metod nie widać różnic w kształcie wykresów ale za to występują przesunięcia względem predykcji. Wyniki są bardzo interesujące, ponieważ umożliwia nam to zobaczenie które zmienne są mocno zależne od innych. Taką zmienną jest np. thalach lub thal_n. Przy czym dla thal_rd już nie ma tak znaczącej różnicy.
ale_rf.result['_label_'] = "ALE"
pdp_rf.result['_label_'] = "PDP"
ale_rf.plot(pdp_rf, variables=var)
Metody PDP bardzo dobrze i rzetelnie oddają specyfikę modelu. Wyniki pokrywają się z naszymi poprzednimi założeniami jak i wnioskami z innych metod XAI. Możemy też zweryfikować wyniki poprzednej metody